package pl.edu.agh.jemo.evolution.specimen.impl;

import pl.edu.agh.jemo.evolution.specimen.Specimen;

/**
 * Extension of Specimen dedicated to use with SPEA2 algorithm.
 * It introduces some more parameters used by selection needed by spea2 algorithm.
 * It doesn't provide any more functionallity than Specimen class.
 * 
 * @author Marcin Zbijowski
 *
 */
public class SPEA2Specimen extends Specimen {

	/**
	 * Number proportional to specimens dominators count.
	 */
	private Double strength = 0.;
	/**
	 * Number determining density of population near specimen.
	 */
	private Double densityFactor = 0.;

	/**
	 * Returns value of specimen's strength.
	 * 
	 * @return Value of strength parameter.
	 */
	public Double getStrength() {
		return strength;
	}

	/**
	 * Sets specimen strength.
	 * 
	 * @param stength New value of strength parameter.
	 */
	public void setStrength(Double stength) {
		this.strength = stength;
	}

	/**
	 * Sets density factor for specimen.
	 * 
	 * @param densityFactor New value of specimen density factor.
	 */
	public void setDensityFactor(Double densityFactor) {
		this.densityFactor = densityFactor;
	}

	/**
	 * Returns number proportional to density of population in specimen neighbourhood.
	 * 
	 * @return Value of density factor population.
	 */
	public Double getDensityFactor() {
		return densityFactor;
	}

	/**
	 * Returns string format human readable specimen summary.
	 * Return srting contains info about genotype, phenotype and fitness of specimen.
	 * It also contains SPEA2Specimen info - strength and density factor.
	 * 
	 * @return String format human readable specimen summary
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(super.toString());
		sb.append("SPEA2:\n");
		sb.append("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
		sb.append("STRENGTH:\n");
		sb.append(String.format("%.4f", strength));
		sb.append("\n");
		sb.append("DENSITY FACTOR:\n");
		sb.append(String.format("%.4f", densityFactor));
		sb.append("\n");
		sb.append("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
		return sb.toString();
	}
	
	/**
	 * Sets all values of new specimen, to be identical with object.
	 * This method is used by clone method. It has been divided from clone to allow it's usage from subclasses and prevent code duplication.
	 * It copies everything copied by Specimen class, strength and density factor.
	 * 
	 * @param spec Specimen, for which values are set to copies of object.
	 */
	protected void prepareCopy(SPEA2Specimen spec) {
		super.prepareCopy(spec);
		spec.densityFactor = densityFactor;
		spec.strength = strength;
	}
	
	/**
	 * Creates new specimen identical to object, and of the same type as object.
	 * 
	 * @return New specimen, that is copy of current specimen.
	 */
	@Override
	public SPEA2Specimen clone() {
		SPEA2Specimen result = null;
		try {
			result = new SPEA2Specimen();
			prepareCopy(result);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		result.setStrength(getStrength());
		result.setDensityFactor(getDensityFactor());
		return result;
	}
}
